package com.yunji.framework_template.biz.service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.yunji.framework_template.biz.cache.CacheService;
import com.yunji.framework_template.biz.cache.EhDataCache;
import com.yunji.framework_template.common.enumeration.NewsType;
import com.yunji.framework_template.common.web.Page;
import com.yunji.framework_template.orm.datasource.HandleDataSource;
import com.yunji.framework_template.orm.persistence.mapper.NewsMapper;
import com.yunji.framework_template.orm.persistence.model.News;
import com.yunji.framework_template.orm.persistence.model.NewsCrawled;

/**
 * Created by fenglibin on 2018/11/26.
 */
@Service
public class NewsService {

    private static final Logger logger = Logger.getLogger(NewsService.class);

    @Resource
    private NewsMapper          newsMapper;
    @Resource
    protected EhDataCache       ehDataCache;
    @Resource
    private NewsCrawledService  newsCrawledService;
    @Resource
    private CacheService        cacheService;
    @Value("#{settings['countryNewsSize']}")
    private int                 countryNewsSize;
    @Value("#{settings['excludeFromAllCountries']}")
    private String              excludeFromAllCountries;

    public int deleteByPrimaryKey(Long id) {
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("newsType", NewsType.getNewsType(id).name());
        param.put("id", id);
        return newsMapper.deleteByPrimaryKey(param);
    }

    public int insert(News record) {
        int result = newsMapper.insert(record);
        if (!(record.getId() == null || record.getId() <= 0)) {
            ehDataCache.put("news-" + String.valueOf(record.getId()), record);
        }
        return result;
    }

    public int insertSelective(News record) {
        int result = newsMapper.insertSelective(record);
        if (!(record.getId() == null || record.getId() <= 0)) {
            ehDataCache.put("news-" + String.valueOf(record.getId()), record);
        }
        return result;
    }

    public News selectByPrimaryKey(Long id) {
        String sid = String.valueOf(id);
        News news = ehDataCache.get("news-" + sid, News.class);
        if (news != null) {
            return news;
        }
        Map<String, Object> param = new HashMap<String, Object>();
        param.put("newsType", NewsType.getNewsType(id).name());
        param.put("id", id);
        news = newsMapper.selectByPrimaryKey(param);
        if (news != null) {
            ehDataCache.put(sid, news);
        }
        return news;
    }

    public int updateByPrimaryKeySelective(News record) {
        int result = newsMapper.updateByPrimaryKeySelective(record);
        if (result > 0) {
            ehDataCache.put("news-" + String.valueOf(record.getId()), selectByPrimaryKey(record.getId()));
        }
        return result;
    }

    public int updateByPrimaryKey(News record) {
        int result = newsMapper.updateByPrimaryKey(record);
        if (result > 0) {
            ehDataCache.put("news-" + String.valueOf(record.getId()), selectByPrimaryKey(record.getId()));
        }
        return result;
    }

    public List<News> selectByCondition(News record) {
        return newsMapper.selectByCondition(record);
    }

    public List<News> selectAll() {
        return newsMapper.selectAll();
    }

    public List<News> selectByPage(Page<News> page) {
        return newsMapper.selectByPage(page);
    }

    public Long count(News record) {
        return newsMapper.count(record);
    }

    public int deleteByCondition(News record) {
        return newsMapper.deleteByCondition(record);
    }

    public String getNewsCachePageKey(long page) {
        return getNewsCachePageKey(HandleDataSource.getDataSource(), page);
    }

    private String getNewsCachePageKey(String countryCode, long page) {
        return countryCode + "-news-latest-" + page;
    }

    /**
     * 根据页码和当前用户登陆的国家，获取当前用户所在国家的分页新闻，每页的默认记录数为15条。<br>
     * 如果用户当前的国家不在所支持的国家中，则从当前所有的已经支持的国家中获取新闻，每个国家对应的当前页返回5条新闻，拼装成结果然后返回给用户。
     * 
     * @param currentPage
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<News> getPageNews(long currentPage) {
        List<News> newsList = new ArrayList<News>();
        if (HandleDataSource.getRealCountryCode() != null
            && cacheService.getCountries().indexOf(HandleDataSource.getRealCountryCode()) >= 0) {// 是当前支持的国家
            newsList = ehDataCache.get(getNewsCachePageKey(currentPage), List.class);
            if (newsList == null || newsList.size() == 0) {// 当前国家没有新闻，则从其它国家获取
                newsList = getNewsFromAllCountries(currentPage);
            }
        } else {// 当前国家还没有支持，则从所有的国家中获取新闻返回
            logger.info("Current country not support:" + HandleDataSource.getRealCountryCode()
                        + ", now get news from all countries.");
            newsList = getNewsFromAllCountries(currentPage);
        }
        if (newsList == null || newsList.size() == 0) {
            newsList = initPageNews(currentPage);
        }
        return newsList;
    }

    /**
     * 根据页码初使化新闻分页
     * 
     * @param currentPage
     * @return
     */
    public List<News> initPageNews(long currentPage) {
        List<News> newsList = new ArrayList<News>();
        long totalCount = cacheService.getCache().getCrawledNews().get();
        Page<NewsCrawled> page = new Page<NewsCrawled>();
        logger.info("initLatestNews,current page:" + currentPage);
        page = page.reverseDisplayCalculate(currentPage, totalCount);
        if (page.getTotalCount() == 0 || page.getTotalPages() == 0) {
            return newsList;
        }
        List<NewsCrawled> list = newsCrawledService.selectByPage(page);
        if (list != null && list.size() > 0) {
            list.forEach(o -> {
                News news = selectByPrimaryKey(o.getNid());
                if (news != null) {
                    newsList.add(news);
                }
            });
            if (!newsList.isEmpty()) {
                ehDataCache.put(getNewsCachePageKey(currentPage), newsList);
            }
        }
        return newsList;
    }

    public int addViewsByPrimaryKey(News record) {
        int result = newsMapper.addViewsByPrimaryKey(record);
        if (result > 0) {
            record.setViews(record.getViews() == null ? 1 : record.getViews() + 1);
            ehDataCache.put("news-" + String.valueOf(record.getId()), record);
        }
        return result;
    }

    public int addLikesByPrimaryKey(News record) {
        int result = newsMapper.addLikesByPrimaryKey(record);
        if (result > 0) {
            record.setLikes(record.getLikes() == null ? 1 : record.getLikes() + 1);
            ehDataCache.put("news-" + String.valueOf(record.getId()), record);
        }
        return result;
    }

    public int addDislikesByPrimaryKey(News record) {
        int result = newsMapper.addDislikesByPrimaryKey(record);
        if (result > 0) {
            record.setDislikes(record.getDislikes() == null ? 1 : record.getDislikes() + 1);
            ehDataCache.put("news-" + String.valueOf(record.getId()), record);
        }
        return result;
    }

    public int addCommentsByPrimaryKey(News record) {
        int result = newsMapper.addCommentsByPrimaryKey(record);
        if (result > 0) {
            record.setComments(record.getComments() == null ? 1 : record.getComments() + 1);
            ehDataCache.put("news-" + String.valueOf(record.getId()), record);
        }
        return result;
    }

    /**
     * 从所有的国家获取新闻
     * 
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<News> getNewsFromAllCountries(long currentPage) {
        List<News> newsList = new ArrayList<News>();
        String[] countryArr = cacheService.getCountries().split(",");
        for (String countryCode : countryArr) {
            if (excludeFromAllCountries.indexOf(countryCode) >= 0) {
                continue;
            }
            List<News> currentNewsList = ehDataCache.get(countryCode, getNewsCachePageKey(countryCode, currentPage),
                                                         List.class);
            if (currentNewsList != null) {
                for (int index = 0; index < currentNewsList.size(); index++) {
                    if (index >= countryNewsSize) {
                        break;
                    }
                    newsList.add(currentNewsList.get(index));
                }
            }
        }
        return newsList;
    }
}
